#pragma once

using namespace std;

// Width and Height of known sizes
typedef struct _HPDF_PageSizeValue {
    HPDF_REAL   x;
    HPDF_REAL   y;
} HPDF_PageSizeValue;

// Conversion : HPDF_REAL / inch = 72
// Conversion : HPDF_REAL / cm = 28.3
static HPDF_PageSizeValue HPDF_PREDEFINED_PAGE_SIZES[] = {
    {(HPDF_REAL)612, (HPDF_REAL)792},     /* PAGE_SIZE_LETTER */
    {(HPDF_REAL)612, (HPDF_REAL)1008},    /* PAGE_SIZE_LEGAL */
    {(HPDF_REAL)841.89, (HPDF_REAL)1199.551},    /* PAGE_SIZE_A3 */
    {(HPDF_REAL)595.276, (HPDF_REAL)841.89},     /* PAGE_SIZE_A4 */
    {(HPDF_REAL)419.528, (HPDF_REAL)595.276},     /* PAGE_SIZE_A5 */
    {(HPDF_REAL)708.661, (HPDF_REAL)1000.63},     /* PAGE_SIZE_B4 */
    {(HPDF_REAL)498.898, (HPDF_REAL)708.661},     /* PAGE_SIZE_B5 */
    {(HPDF_REAL)522, (HPDF_REAL)756},     /* PAGE_SIZE_EXECUTIVE */
    {(HPDF_REAL)(HPDF_REAL)288, (HPDF_REAL)432},     /* PAGE_SIZE_US4x6 */
    {(HPDF_REAL)288, (HPDF_REAL)576},     /* PAGE_SIZE_US4x8 */
    {(HPDF_REAL)360, (HPDF_REAL)504},     /* PAGE_SIZE_US5x7 */
    {(HPDF_REAL)297, (HPDF_REAL)684},     /* PAGE_SIZE_COMM10 */
	{(HPDF_REAL)576, (HPDF_REAL)720},     /* PAGE_SIZE_US8x10 */
	{(HPDF_REAL)648, (HPDF_REAL)864},     /* PAGE_SIZE_US9x12 */
	{(HPDF_REAL)252, (HPDF_REAL)360},     /* PAGE_SIZE_US3_5x5 */
	{(HPDF_REAL)180, (HPDF_REAL)252},     /* PAGE_SIZE_WALLET */
	{(HPDF_REAL)905.6, (HPDF_REAL)1313.12}      /* PAGE_SIZE_320x464cm */
};

enum HPDF_PAGESIZES {
    PAGE_SIZE_LETTER = 0,
    PAGE_SIZE_LEGAL,
    PAGE_SIZE_A3,
    PAGE_SIZE_A4,
    PAGE_SIZE_A5,
    PAGE_SIZE_B4,
    PAGE_SIZE_B5,
    PAGE_SIZE_EXECUTIVE,
    PAGE_SIZE_US4x6,
    PAGE_SIZE_US4x8,
    PAGE_SIZE_US5x7,
    PAGE_SIZE_COMM10,
	PAGE_SIZE_US8x10,
	PAGE_SIZE_US9x12,
	PAGE_SIZE_US3_5x5,
	PAGE_SIZE_WALLET,
	PAGE_SIZE_320x464cm,
    PAGE_SIZE_EOF
};

// A definition for each image inside a page.
struct IMAGE_DEFINITIONS{
public:
	wstring FilePath;	// Path to the image file
	bool DrawBorders;	// Draw borders around images
	int ImageIdx;		// The index of the image inside the page
						// (image0 will be on top of image1 and image1 on top of image2)

	// If ONE OF THESE parameters is -1, The image's Width and Height will be calculated automatically
	HPDF_REAL Width;
	HPDF_REAL Height;

	// If ONE OF THESE parameters is -1, The image's LocX and LocY will be calculated automatically
	HPDF_REAL LocX;
	HPDF_REAL LocY;

	IMAGE_DEFINITIONS()
		: DrawBorders(false), ImageIdx(-1), Width(-1), Height(-1), LocX(-1), LocY(-1)
	{}

	void SetFilePath(const wstring& newFile)
	{
		FilePath = newFile;
	}
};

// A definition of each page inside the PDF file.
struct PDFPage{
public:
	HPDF_PAGESIZES Size;
	HPDF_REAL Margin;
	
	bool ImgsLeftToRight;				// Determines whether to put images top to bottom or left to right
	bool IsLandscape;					// Determines if the page will be portrait or landscape
	HPDF_UINT16 Rotation;				// The rotation of the page from it's initial position (if IsLandscape then initial position is 90deg)
										// Rotation can only be: 0,90,180,270
	bool OptimizeImages;

	list<IMAGE_DEFINITIONS> ImageDefs;	// A list of image definitions for the images on the curent page

	PDFPage()
		: Rotation(0), Size(PAGE_SIZE_A4), IsLandscape(false), ImgsLeftToRight(true), Margin(28), OptimizeImages(false)
	{}

	PDFPage(HPDF_PAGESIZES size, HPDF_REAL margin, bool imgsLeftToRight, bool isLandscape,
		HPDF_UINT16 rotation, bool optimizeImages)
		: Rotation(rotation), Size(size), IsLandscape(isLandscape), 
		ImgsLeftToRight(imgsLeftToRight), Margin(margin), OptimizeImages(optimizeImages)
	{}

	~PDFPage() { }
	
	void ClearImages() 
	{
		ImageDefs.clear();
	}

	void AddImage(const wstring& filePath, bool drawBorders, int index, HPDF_REAL width, 
		HPDF_REAL height, HPDF_REAL locX, HPDF_REAL locY)
	{
		IMAGE_DEFINITIONS id;
		id.FilePath = filePath;
		id.DrawBorders = drawBorders;
		id.ImageIdx = index;
		id.Width = width;
		id.Height = height;
		id.LocX = locX;
		id.LocY = locY;

		ImageDefs.push_back(id);
	}

	void AddImage(const IMAGE_DEFINITIONS& img)
	{
		ImageDefs.push_back(img);
	}
};

struct PDFFile{
public:
	wstring FilePath;
	list<PDFPage> Pages;

	PDFFile(const wstring& filePath)
		: FilePath(filePath)
	{}
	~PDFFile(){}

	void AddPage(const PDFPage& page)
	{
		Pages.push_back(page);
	}
};
